package com.yuqq;

import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class ExcelDeduplication2 {

    public static void main(String[] args) {
        // 输入 Excel 文件路径，需替换为实际路径
        String inputPath = "src/main/resources/output87.xlsx";
        // 输出 Excel 文件路径，需替换为实际路径
        String outputPath = "src/main/resources/output88.xlsx";
        try {
            // 读取 Excel 文件
            Workbook workbook = new XSSFWorkbook(new FileInputStream(new File(inputPath)));
            Sheet sheet = workbook.getSheetAt(0); // 假设处理第一个工作表

            // 用于按行内容分组，key 是行内容拼接字符串，value 是该行号以及第二列是否有值的信息列表
            Map<String, List<RowInfo>> rowContentMap = new HashMap<>();
            int lastRowNum = sheet.getLastRowNum();
            for (int rowIndex = 0; rowIndex <= lastRowNum; rowIndex++) {
                Row row = sheet.getRow(rowIndex);
                if (row == null) {
                    continue;
                }
                // 获取行内容拼接成字符串，作为 map 的 key，这里简单用制表符分隔单元格内容
                String rowKey = getRowContent(row);
                Cell secondCell = row.getCell(1); // 假设第二列是索引为 1 的单元格（从 0 开始）
                boolean hasSecondColumnValue = false;
                if (secondCell != null) {
                    // 判断第二列是否有值，只要不是空白单元格就算有值
                    hasSecondColumnValue = secondCell.getCellType() != CellType.BLANK;
                }
                RowInfo rowInfo = new RowInfo(rowIndex, hasSecondColumnValue);
                rowContentMap.computeIfAbsent(rowKey, k -> new ArrayList<>()).add(rowInfo);
            }

            // 记录需要删除的行号
            List<Integer> rowsToDelete = new ArrayList<>();

            for (Map.Entry<String, List<RowInfo>> entry : rowContentMap.entrySet()) {
                List<RowInfo> rowInfos = entry.getValue();
                if (rowInfos.size() <= 1) {
                    // 只有一行，无需处理
                    continue;
                }
                // 先判断是否存在第二列有值和无值混合的情况
                boolean hasMixed = false;
                boolean hasValueInSecond = false;
                for (RowInfo info : rowInfos) {
                    if (info.hasSecondColumnValue) {
                        hasValueInSecond = true;
                    } else {
                        hasMixed = true;
                    }
                }
                if (hasMixed) {
                    // 情况 3：有值和无值重复，删掉第二列没有值的数据
                    for (RowInfo info : rowInfos) {
                        if (!info.hasSecondColumnValue) {
                            rowsToDelete.add(info.rowIndex);
                        }
                    }
                    continue;
                }

                // 不管第二列有无值，只要重复行数大于 1，都删除除最后一行外的其他行
                if (rowInfos.size() > 1) {
                    for (int i = 0; i < rowInfos.size() - 1; i++) {
                        rowsToDelete.add(rowInfos.get(i).rowIndex);
                    }
                }
            }

            // 从后往前删除行，避免行号变化影响
            rowsToDelete.sort((o1, o2) -> o2 - o1);
            for (int rowIndex : rowsToDelete) {
                deleteRow(sheet, rowIndex);
            }

            // 写入处理后的内容到新文件
            try (FileOutputStream fos = new FileOutputStream(outputPath)) {
                workbook.write(fos);
            }
            System.out.println("去重完成，结果已输出到: " + outputPath);

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    // 获取行内容拼接成字符串，简单用制表符连接单元格内容
    private static String getRowContent(Row row) {
        List<String> cellValues = new ArrayList<>();
        int lastCellNum = row.getLastCellNum();
        for (int cellIndex = 0; cellIndex < lastCellNum; cellIndex++) {
            Cell cell = row.getCell(cellIndex);
            if (cell == null) {
                cellValues.add("");
            } else {
                switch (cell.getCellType()) {
                    case STRING:
                        cellValues.add(cell.getStringCellValue());
                        break;
                    case NUMERIC:
                        if (DateUtil.isCellDateFormatted(cell)) {
                            cellValues.add(String.valueOf(cell.getDateCellValue()));
                        } else {
                            cellValues.add(String.valueOf(cell.getNumericCellValue()));
                        }
                        break;
                    case BOOLEAN:
                        cellValues.add(String.valueOf(cell.getBooleanCellValue()));
                        break;
                    case BLANK:
                        cellValues.add("");
                        break;
                    default:
                        cellValues.add("");
                }
            }
        }
        return String.join("\t", cellValues);
    }

    // 删除指定行号的行
    private static void deleteRow(Sheet sheet, int rowIndex) {
        int lastRowNum = sheet.getLastRowNum();
        if (rowIndex >= 0 && rowIndex < lastRowNum) {
            sheet.shiftRows(rowIndex + 1, lastRowNum, -1);
        }
        if (rowIndex == lastRowNum) {
            Row row = sheet.getRow(rowIndex);
            if (row != null) {
                sheet.removeRow(row);
            }
        }
    }

    // 辅助类，记录行号和第二列是否有值
    static class RowInfo {
        int rowIndex;
        boolean hasSecondColumnValue;

        public RowInfo(int rowIndex, boolean hasSecondColumnValue) {
            this.rowIndex = rowIndex;
            this.hasSecondColumnValue = hasSecondColumnValue;
        }
    }
}